﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.ComponentModel;
using System.Windows.Forms;

namespace Assignment2
{
    //************************************************************************
    //*
    //*  ChickenFarm Class.
    //*
    //************************************************************************

    public class ChickenFarm
    {
        //************************************************************************
        //*
        //*  Member variables
        //*
        //************************************************************************
        
        private PricingModel _pricingModel;
        private OrderProcessing _processor;

        // price cut event
        public static event PriceCutEvent price_cut_event;

        // retailer shutdown event
        public static event RetailerShutdownEvent retailer_shutdown_event;

        // current chicken price
        Int32 _price;

        private bool _keepAlive;

        // the count of pricecuts
        private int _priceCutCount;

        private DateTime startTime;
        private DateTime endTime;

        private static Random _priceCheckWaitTime;


        //************************************************************************
        //*
        //*  Constructor
        //*
        //************************************************************************

        public ChickenFarm()
        {
            

            // create the PricingModel object
            _pricingModel = new PricingModel();            

            // set the current chicken price
            _price = _pricingModel.getPrice();

            // create the order processor
            _processor = new OrderProcessing(_price);

            // keep alive
            _keepAlive = true;

            // initialize the price cut count
            _priceCutCount = 0;

            // register with the MultiCellBuffer event callback scheme
            MultiCellBuffer.order_notify += new OrderNotification(check_orders);
            
            // seed the price check time
            _priceCheckWaitTime = new Random();
        }

        //************************************************************************
        //*
        //*  Start the main loop thread for the Chicken Farm
        //*
        //************************************************************************

        public void start()
        {
            this.startTime = DateTime.Now;
            Logger.log_message("ChickenFarm start time: " + this.startTime.ToString("MM/dd/yyyy HH:mm:ss.ffff"));
            Console.WriteLine("ChickenFarm start time: " + this.startTime.ToString("MM/dd/yyyy HH:mm:ss.ffff"));

            while (_keepAlive == true)
            {
                // Random wait time before checking the price model again
                int sleep_time = _priceCheckWaitTime.Next(3000);
                Thread.Sleep(sleep_time);
                this.check_price();
            }

            // provide feedback that the chicken farm has completed
            Console.WriteLine("ChickenFarm has completed 10 price cuts and is shutting down!");

            // kill the retailers
            this._killClients();

            this.endTime = DateTime.Now;
            Logger.log_message("ChickenFarm start time: " + this.endTime.ToString("MM/dd/yyyy HH:mm:ss.ffff"));
            Console.WriteLine("ChickenFarm start time: " + this.endTime.ToString("MM/dd/yyyy HH:mm:ss.ffff"));

            TimeSpan span = this.endTime - this.startTime;
            Logger.log_message("ChickenFarm total time: " + span.Seconds + "." + span.Milliseconds);
            Console.WriteLine("ChickenFarm total time: " + span.Seconds + "." + span.Milliseconds);
            Console.WriteLine("Press enter to calculate average response time");
        }        

        //************************************************************************
        //*
        //*  Kill all clients
        //*
        //************************************************************************

        private void _killClients()
        {
            // make sure there is at least 1 subscriber
            if (retailer_shutdown_event != null)
            {
                String message =
                    "ChickenFarm is shutting down.  Sending shutdown order to retailers.";
                // Proved feedback
                Console.WriteLine(message);

                // fire the price cut event
                retailer_shutdown_event();
            }
        }       

        //*************************************************************************************
        //*
        //*  Check on orders
        //*
        //*************************************************************************************

        private void check_orders()
        {
            try
            {
                // get an order and process it
                String encoded_order = MultiCellBuffer.getOneCell();

                // decode the order
                Decoder decoder = new Decoder(encoded_order);
                Order order = decoder.decode();
                
                // place the order
                _processor.add(order);

            }
            catch (Exception)
            {
                String message = "Unable to place order.  Client with id not found";
                Logger.log_message(message);
            }

            
        }

        //*************************************************************************************
        //*
        //*  Check and update the price
        //*
        //*************************************************************************************

        private void check_price()
        {
            // check for new price and update
            int price = _pricingModel.getPrice();

            // check the price against the current price
            if (price < _price)
            {
                // make sure there is at least 1 subscriber
                if (price_cut_event != null)
                {
                    // Proved feedback
                    Console.WriteLine(
                        "ChickenFarm: Price Cut! [" +
                        "Old price ({0}) | New price({1}) ]", 
                        _price.ToString(), price.ToString());

                    // fire the price cut event
                    price_cut_event(price);
                }

                // increment and check the price cut count
                _priceCutCount++;
                if (_priceCutCount >= 10)
                {
                    _keepAlive = false;
                }
            }

            // Provide feedback on a price cut
            if (_price != price)
            {
                Console.WriteLine("New chicken price is {0}!", price);
            }

            // update the price
            _price = price;
        }
    }


}
